import React, { useState, FC, ReactNode, MouseEventHandler, MouseEvent, createContext, useContext } from "react";
import "./index.less";

// TODO 应独立生成组件
// import Tag from "@gaoges-ui/tag";
import Tag from "./reference/Tag/index";
import Avatar, { AvatarProps } from "@mui/material/Avatar";
import ArrowBackSharpIcon from "@mui/icons-material/ArrowBackSharp";
import Button from "@mui/material/Button";
import IconButton, { IconButtonProps } from "@mui/material/IconButton";
import Menu from "@mui/material/Menu";
import MenuItem, { MenuItemProps } from "@mui/material/MenuItem";
import Breadcrumbs, { BreadcrumbsProps } from "@mui/material/Breadcrumbs";
import Link, { LinkProps } from "@mui/material/Link";
import Box from "@mui/material/Box";
import { _prefixCls, _mergeCls } from "@gaoges/utils";

_prefixCls("giui-page-header-");

interface initialContextProps {
  useLocation?: () => { pathname: string };
  routeList?: routeProps[];
}

const initialContext: initialContextProps = {};

const Context = createContext(initialContext);

interface menuModelProps {
  text?: string;
  icon?: ReactNode;
  menuOptions: any;
}

interface crumbProps extends LinkProps {
  path?: string;
  children: string;
}

interface PageHeaderProps {
  className?: string;
  title: string;
  subTitle?: string;
  ghost?: boolean;
  tags?: any[];
  extra?: ReactNode;
  avatar?: AvatarProps;
  menuModel?: menuModelProps;
  crumbs?: crumbProps[];
  children?: any;
  onBack?: () => void;
}

interface routeProps {
  page?: string;
  name: string;
}

interface ProviderProps {
  useLocation: any;
  routeList: routeProps[];
}

type PageHeaderInstance<P> = FC<P> & {
  Provider: typeof Provider;
};

const Provider: FC<ProviderProps> = ({ useLocation, routeList, children }) => {
  return <Context.Provider value={{ useLocation, routeList }}>{children}</Context.Provider>;
};

const PageHeader: PageHeaderInstance<PageHeaderProps> = ({
  title,
  subTitle,
  ghost,
  tags,
  extra,
  avatar,
  menuModel,
  crumbs,
  children,
  onBack
}) => {
  const { useLocation, routeList } = useContext(Context);
  const [pattern, setPattern] = useState("light");
  const TagsNode = !tags ? tags : tags.map(tagProps => <Tag key={"tag-key-" + tagProps.context} {...tagProps} />);
  const [menuOpen, setMenuOpen] = useState(false);
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);

  const MenuBtnhandleClick = (event: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>) => {
    setMenuOpen(true);
    setAnchorEl(event.currentTarget);
  };

  const cutMenuItemFn = (event: MouseEvent, fn: MouseEventHandler | undefined) => {
    setMenuOpen(false);
    setAnchorEl(null);
    fn && fn(event);
  };

  const getMenuBtn = (text?: string, icon?: ReactNode) => {
    if (text) {
      return (
        <Button id="basic-button" onClick={event => MenuBtnhandleClick(event)}>
          {text}
        </Button>
      );
    }
    if (icon) {
      return (
        <IconButton id="basic-button" onClick={event => MenuBtnhandleClick(event)}>
          {icon}
        </IconButton>
      );
    }
  };

  const getMenuItemKey = (option: MenuItemProps) => {
    if (typeof option === "string") {
      return "MenuItem-key-" + option;
    }
  };

  const getMenuModelNode = () => {
    if (!menuModel) return null;
    const { text, icon, menuOptions } = menuModel;
    const menuBtn = getMenuBtn(text, icon);
    const menuNode = (
      <Menu
        id="long-menu"
        MenuListProps={{
          "aria-labelledby": "long-button"
        }}
        anchorEl={anchorEl}
        open={menuOpen}
        onClose={() => setMenuOpen(false)}
        PaperProps={{
          style: {
            maxHeight: 48 * 4.5
          }
        }}>
        {menuOptions.map((option: MenuItemProps) => (
          <MenuItem key={getMenuItemKey(option)} onClick={event => cutMenuItemFn(event, option.onClick)}>
            {option}
          </MenuItem>
        ))}
      </Menu>
    );
    return (
      <>
        {menuBtn}
        {menuNode}
      </>
    );
  };

  const getHeaderLeftContext = () => {
    return (
      <>
        {onBack && <ArrowBackSharpIcon className="back-icon" onClick={onBack} />}
        {avatar && <Avatar {...avatar} style={{ marginRight: "14px" }} />}
        <div className={_prefixCls("heading-context")}>
          <span className={_prefixCls("heading-title")}>{title}</span>
          <span className={_prefixCls("heading-sub-title")}>{subTitle}</span>
          {TagsNode}
        </div>
      </>
    );
  };

  const getHeaderRightContext = () => {
    return (
      <div className={_prefixCls("heading-right-operate")}>
        {extra}
        <div className={_prefixCls("heading-right-operate-dropdown")}> {menuModel && getMenuModelNode()}</div>
      </div>
    );
  };

  const createCrumbs = (pathname: string) => {
    let nodes = pathname.split("/");
    nodes.shift();

    return nodes.map((node, index) => {
      const route = routeList?.find((route: routeProps) => route.page === node);
      return {
        children: route ? route.name : "",
        path: route ? "/" + [...nodes].splice(0, index + 1).join("/") : ""
      };
    });
  };

  const autoCrumbs = () => {
    if (!useLocation) return;
    const { pathname } = useLocation();
    const crumbs: crumbProps[] = createCrumbs(pathname);

    return (
      <Box mb={1}>
        <Breadcrumbs>
          {crumbs.map((crumb: crumbProps, index) => {
            if (index === crumbs.length - 1) {
              return (
                <Link
                  key={"link-key-" + crumb.children}
                  underline="none"
                  variant="body2"
                  sx={{
                    color: "rgba(0,0,0,.75)"
                  }}>
                  {crumb.children}
                </Link>
              );
            }
            return (
              <Link
                key={"link-key-" + crumb.children}
                underline="hover"
                variant="body2"
                sx={{
                  color: "rgba(0,0,0,.45)",
                  ":hover": {
                    color: "#0072E5"
                  }
                }}
                href={crumb.path}>
                {crumb.children}
              </Link>
            );
          })}
        </Breadcrumbs>
      </Box>
    );
  };

  const getCrumbs = () => {
    if (routeList) return autoCrumbs();
    else if (crumbs) {
      return (
        <Box mb={1}>
          <Breadcrumbs>
            {crumbs.map((crumb: crumbProps, index) => {
              if (index === crumbs.length - 1) {
                return (
                  <Link
                    key={"link-key-" + crumb.children}
                    underline="none"
                    variant="body2"
                    sx={{
                      color: "rgba(0,0,0,.75)"
                    }}>
                    {crumb.children}
                  </Link>
                );
              }
              return (
                <Link
                  key={"link-key-" + crumb.children}
                  underline="hover"
                  variant="body2"
                  sx={{
                    color: "rgba(0,0,0,.45)",
                    ":hover": {
                      color: "#0072E5"
                    }
                  }}
                  href={crumb.path}>
                  {crumb.children}
                </Link>
              );
            })}
          </Breadcrumbs>
        </Box>
      );
    } else return null;
  };

  return (
    <div className={_mergeCls(_prefixCls("wrapper"), ghost ? "ghost" : null)} color-scheme={pattern}>
      {getCrumbs()}
      <div className={_prefixCls("heading")}>
        <div className={_prefixCls("heading-left")}>{getHeaderLeftContext()}</div>
        <div className={_prefixCls("heading-right")}>{getHeaderRightContext()}</div>
      </div>
      <section className={_prefixCls("body")}>{children}</section>
    </div>
  );
};

PageHeader.Provider = Provider;
PageHeader.defaultProps = {
  ghost: false
};

export default PageHeader;
